import * as THREE from "three";
import { Octree } from 'three/addons/math/Octree.js';
import { OctreeHelper } from 'three/examples/jsm/helpers/OctreeHelper.js';
import { Capsule } from 'three/addons/math/Capsule.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { gui } from "../system/gui";
import CapsuleHelper from "./CapsuleHelper";
import io from 'socket.io-client';
import { ElMessage } from "element-plus";

//#region 类型定义与常量设置
const ANIMATION = {
    IDLE: "Breathing Idle",
    WALK: "Walking",
    RUN: "Standard Run"
} as const;
export type AnimationType = typeof ANIMATION[keyof typeof ANIMATION];

export interface PlayerState {
    position: THREE.Vector3;
    rotation: THREE.Euler;
}

const GRAVITY = 30;
const DEFAULT_COLLIDER_RADIUS = 0.35;
const DEFAULT_COLLIDER_BOTTOM_Y = 0.35;
const DEFAULT_COLLIDER_TOP_Y = 1.5;
const CURVE_VELOCITY = 0.001;
//#endregion


//#region 全局变量声明
// 主控对象（例如 Three.js 应用对象），后续统一赋值
let that: any;

// 宝箱模型相关
let chest: THREE.Object3D | null = null;
let chestMixer: THREE.AnimationMixer | null = null;
let chestAction: THREE.AnimationAction | null = null;
let isChestOpen = false;
let chestHintSprite: THREE.Sprite | null = null;

// 网络相关
let socket: any;
let localPlayerId: string | null = null;
const remotePlayers: Record<string, {
    model: THREE.Group;
    targetPosition: THREE.Vector3;
    targetRotation: THREE.Euler;
    mixer: THREE.AnimationMixer;
    actions: Record<AnimationType, THREE.AnimationAction>;
    currentAction: AnimationType;
    collider: Capsule;
    velocity: THREE.Vector3;
    onFloor: boolean;
}> = {};

// 场景与物理数据
const worldOctree = new Octree();
const playerCollider = new Capsule(
    new THREE.Vector3(0, DEFAULT_COLLIDER_BOTTOM_Y, 0),
    new THREE.Vector3(0, DEFAULT_COLLIDER_TOP_Y, 0),
    DEFAULT_COLLIDER_RADIUS
);
const playerColliderHelper = CapsuleHelper(0.6, 1.5);
const playerFixVector = new THREE.Vector3(0, DEFAULT_COLLIDER_BOTTOM_Y, 0);
const playerVelocity = new THREE.Vector3();
const playerDirection = new THREE.Vector3();
let playerOnFloor = false;

// 曲线与模型动画
let model: THREE.Object3D;
let curve: THREE.CatmullRomCurve3;
let progress = 0;

// 时钟与灵敏度设置
let ForwardHoldTimeClock = new THREE.Clock();
ForwardHoldTimeClock.autoStart = false;
let cameraMoveSensitivity = 0.4;
gui.add({ cameraMoveSensitivity }, "cameraMoveSensitivity")
    .name("视角拖动灵敏度延迟")
    .step(0.1)
    .min(0)
    .max(1)
    .onChange((value: number) => { cameraMoveSensitivity = value; });

// 输入与控制状态
const keyStates = {
    W: false, A: false, S: false, D: false, KeyF: false,
    ShiftLeft: false, Space: false, leftMouseBtn: false
};

const playerActionState = {
    forward: 0,
    turn: 0
};

const obj = { look: false };
//#endregion

//#region 天气系统
let rainParticles: THREE.Points;
const RAIN_COUNT = 50000;
let rainEnabled = false;

// 添加着色器 uniforms
const rainUniforms = {
    time: { value: 0 },
    speed: { value: 15 },
    windStrength: { value: 0.5 }
};

// 添加GUI控制参数
const rainParams = {
    speed: 15,
    wind: 0.5,
    particleSize: 2.0
};

// GUI控件
const rainFolder = gui.addFolder('下雨效果');
rainFolder.add({ rainEnabled }, 'rainEnabled')
    .name('开启/关闭')
    .onChange((value: boolean) => {
        rainEnabled = value;
        if (rainParticles) {
            rainParticles.visible = value;
        }
    });
rainFolder.add(rainParams, 'speed', 5, 30).name('下落速度').onChange(v => rainUniforms.speed.value = v);
rainFolder.add(rainParams, 'wind', 0, 2).name('风力强度').onChange(v => rainUniforms.windStrength.value = v);
rainFolder.add(rainParams, 'particleSize', 1, 5).name('雨滴大小').onChange(v => {
    const shaderMaterial = rainParticles.material as THREE.ShaderMaterial;
    const vs = shaderMaterial.vertexShader.replace(
        /gl_PointSize\s*=\s*\d+\.?\d*/,
        `gl_PointSize = ${v.toFixed(1)}`
    );
    shaderMaterial.vertexShader = vs;
    shaderMaterial.needsUpdate = true;
});

function createRainEffect() {
    if (rainParticles) return;

    const geometry = new THREE.BufferGeometry();
    const positions = new Float32Array(RAIN_COUNT * 3);
    const randoms = new Float32Array(RAIN_COUNT); // 添加随机数属性

    for (let i = 0; i < RAIN_COUNT; i++) {
        positions[i * 3] = (Math.random() - 0.5) * 200;
        positions[i * 3 + 1] = Math.random() * 150;
        positions[i * 3 + 2] = (Math.random() - 0.5) * 200;
        randoms[i] = Math.random(); // 为每个粒子保存随机数
    }

    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    geometry.setAttribute('aRandom', new THREE.BufferAttribute(randoms, 1));

    // 使用 ShaderMaterial 替换 PointsMaterial
    const material = new THREE.ShaderMaterial({
        uniforms: rainUniforms,
        vertexShader: `
            uniform float time;
            uniform float speed;
            uniform float windStrength;
            attribute float aRandom;
            
            varying float vAlpha;
            
            void main() {
                // 粒子运动计算
                float t = mod(time * 0.5 + aRandom * 10.0, 10.0);
                vec3 newPosition = position;
                
                // Y轴下落 + 随机XZ偏移
                newPosition.y -= t * speed;
                newPosition.x += sin(time * 2.0 + aRandom) * windStrength;
                newPosition.z += cos(time * 1.5 + aRandom) * windStrength;
                
                // 重置位置
                if(newPosition.y < -50.0) {
                    newPosition.y += 200.0;
                }
                
                // 透明度变化
                vAlpha = smoothstep(0.0, 0.2, t) * (1.0 - smoothstep(7.0, 10.0, t));
                
                gl_PointSize = 2.0;
                gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
            }
        `,
        fragmentShader: `
            varying float vAlpha;
            
            void main() {
                // 雨滴形状（圆形渐变）
                vec2 uv = gl_PointCoord - 0.5;
                float len = length(uv);
                float alpha = smoothstep(0.4, 0.3, len) * vAlpha;
                
                gl_FragColor = vec4(0.6, 0.7, 1.0, alpha);
            }
        `,
        transparent: true,
        depthWrite: false
    });

    rainParticles = new THREE.Points(geometry, material);
    rainParticles.visible = rainEnabled;
    that.scene.add(rainParticles);
}

function updateRainEffect(deltaTime: number) {
    if (!rainParticles || !rainEnabled) return;

    // 更新着色器时间
    rainUniforms.time.value += deltaTime;

    // 添加风场变化
    rainUniforms.windStrength.value = Math.sin(rainUniforms.time.value * 0.5) * 0.8;
}
//#endregion

//#region 物理与角色控制相关函数
function playerCollisions() {
    const result = worldOctree.capsuleIntersect(playerCollider);
    playerOnFloor = false;
    if (result) {
        playerOnFloor = result.normal.y > 0;
        if (!playerOnFloor) {
            playerVelocity.addScaledVector(result.normal, -result.normal.dot(playerVelocity));
        }
        playerCollider.translate(result.normal.multiplyScalar(result.depth));
    }
}

function updatePlayer(deltaTime: number) {
    if (!(that.player instanceof THREE.Object3D)) return;

    let speedRatio = 1.5;
    let damping = Math.exp(-20 * deltaTime) - 1;
    let effectiveDamping = damping;

    if (!playerOnFloor) {
        playerVelocity.y -= GRAVITY * deltaTime;
        // 非地面状态时降低阻尼影响
        effectiveDamping *= 0.1;
        speedRatio = 2;
    }
    playerVelocity.addScaledVector(playerVelocity, effectiveDamping);

    // 控制前进与转向动画
    if (playerActionState.forward > 0) {
        if (playerActionState.turn !== 0) {
            that.player.rotation.y -= playerActionState.turn * deltaTime * 2;
        }
        if (ForwardHoldTimeClock.getElapsedTime() > 2 || (keyStates.ShiftLeft && keyStates.W)) {
            if (playerOnFloor) speedRatio = 5;
            changeAction(ANIMATION.RUN);
        } else {
            changeAction(ANIMATION.WALK);
        }
    } else if (playerActionState.forward < 0) {
        changeAction(ANIMATION.WALK);
    } else if (playerActionState.turn !== 0) {
        changeAction(ANIMATION.WALK);
        that.player.rotation.y -= playerActionState.turn * deltaTime * 2;
    } else {
        changeAction(ANIMATION.IDLE);
    }

    const deltaPosition = playerVelocity.clone().multiplyScalar(deltaTime * speedRatio);
    // 对 y 轴分量不应用速度系数
    deltaPosition.y /= speedRatio;
    playerCollider.translate(deltaPosition);

    playerCollisions();

    // 使用修正向量保证角色触地
    that.player.position.copy(new THREE.Vector3().subVectors(playerCollider.start, playerFixVector));
}

function getForwardVector(): THREE.Vector3 {
    that.player.getWorldDirection(playerDirection);
    playerDirection.y = 0;
    return playerDirection.normalize();
}

function getSideVector(): THREE.Vector3 {
    that.player.getWorldDirection(playerDirection);
    playerDirection.y = 0;
    playerDirection.normalize();
    playerDirection.cross(that.player.up);
    return playerDirection;
}

function controls(deltaTime: number) {
    const speedDelta = deltaTime * (playerOnFloor ? 25 : 8);
    if (keyStates.W) playerVelocity.add(getForwardVector().multiplyScalar(speedDelta));
    if (keyStates.S) playerVelocity.add(getForwardVector().multiplyScalar(-speedDelta));
    if (keyStates.A) playerVelocity.add(getSideVector().multiplyScalar(-speedDelta));
    if (keyStates.D) playerVelocity.add(getSideVector().multiplyScalar(speedDelta));
    if (playerOnFloor && keyStates.Space) {
        playerVelocity.y = 15;
    }
}

function teleportPlayerIfOob() {
    if (!(that.player instanceof THREE.Object3D)) return;
    if (that.player.position.y <= -25) {
        playerCollider.start.set(0, DEFAULT_COLLIDER_BOTTOM_Y, 0);
        playerCollider.end.set(0, DEFAULT_COLLIDER_TOP_Y, 0);
        playerCollider.radius = DEFAULT_COLLIDER_RADIUS;
        that.player.position.copy(new THREE.Vector3().subVectors(playerCollider.start, playerFixVector));
        that.player.rotation.set(0, 0, 0);
    }
}

function changeAction(action: AnimationType) {
    if (!that.allActions[action]) {
        console.warn(`尝试切换不存在的动作: ${action}`);
        return;
    }
    if (that.currentAction.name !== action) {
        that.currentAction.fadeOut(0.2);
        that.allActions[action].reset().setEffectiveWeight(1).fadeIn(0.2).play();
        that.currentAction = that.allActions[action];
    }
}
//#endregion
//#region 模型动画及曲线运动
function makeCurve() {
    curve = new THREE.CatmullRomCurve3([
        new THREE.Vector3(28, -10, -75),
        new THREE.Vector3(28, -10, -70),
        new THREE.Vector3(33, -10, -75)
    ]);
    curve.curveType = "catmullrom";
    curve.closed = true;
    curve.tension = 1;
}

function moveOnCurve() {
    if (!curve || !model) {
        // 如果曲线或模型未加载完成，则不执行任何操作
        console.log("场景加载中...");
        return;
    }
    if (progress <= 1 - CURVE_VELOCITY) {
        const point = curve.getPointAt(progress);
        const pointNext = curve.getPointAt(progress + CURVE_VELOCITY);
        if (point && pointNext) {
            model.position.set(point.x, point.y, point.z);
            const offsetAngle = Math.PI;
            const mtx = new THREE.Matrix4();
            mtx.lookAt(model.position, pointNext, model.up);
            mtx.multiply(new THREE.Matrix4().makeRotationY(offsetAngle));
            const toRot = new THREE.Quaternion().setFromRotationMatrix(mtx);
            model.quaternion.slerp(toRot, 0.2);
        }
        progress += CURVE_VELOCITY;
    } else {
        progress = 0;
    }
}

function animateCurve() {
    requestAnimationFrame(animateCurve);
    moveOnCurve();
}
//#endregion

//#region 调试信息显示
function createDebugOverlay() {
    const div = document.createElement('div');
    Object.assign(div.style, {
        position: 'fixed',
        top: '9rem',
        left: '10px',
        color: 'white',
        backgroundColor: 'rgba(0,0,0,0.7)',
        padding: '10px',
        fontFamily: 'Arial, sans-serif',
        fontSize: '14px',
    });
    document.body.appendChild(div);

    setInterval(() => {
        const info = Object.entries(remotePlayers).map(([id, p]) => {
            const pos = p.model.position;
            return `远程玩家ID: ${id}<br>实际位置: (${pos.x.toFixed(2)}, ${pos.y.toFixed(2)}, ${pos.z.toFixed(2)})<br>当前动作: ${p.currentAction}`;  // 新增动作显示
        }).join('<br><br>');
        if (!(that.player instanceof THREE.Object3D)) return;
        div.innerHTML = `本地玩家ID: ${localPlayerId}<br>实际位置: (${that.player.position.x.toFixed(2)}, ${that.player.position.y.toFixed(2)}, ${that.player.position.z.toFixed(2)})<br>----------------------------------------------------<br>${info}`;
    }, 100);
}
//#endregion

//#region 远程玩家处理
function createRemotePlayer(id: string, position: THREE.Vector3, rotation: THREE.Euler, action?: AnimationType) {
    const collider = new Capsule(
        new THREE.Vector3(position.x, position.y + DEFAULT_COLLIDER_BOTTOM_Y, position.z),
        new THREE.Vector3(position.x, position.y + DEFAULT_COLLIDER_TOP_Y, position.z),
        DEFAULT_COLLIDER_RADIUS
    );
    const tempModel = new THREE.Group();
    tempModel.position.copy(position);
    tempModel.rotation.copy(rotation);
    that.scene.add(tempModel);

    remotePlayers[id] = {
        model: tempModel,
        targetPosition: position.clone(),
        targetRotation: rotation.clone(),
        mixer: null as any,
        actions: {} as Record<AnimationType, THREE.AnimationAction>,
        currentAction: action || ANIMATION.IDLE,
        collider,
        velocity: new THREE.Vector3(),
        onFloor: false
    };

    // 加载远程玩家模型
    const loader = new GLTFLoader().setPath('/models/');
    loader.load("fish.glb", (gltf) => {
        const remoteModel = gltf.scene;
        remoteModel.traverse((obj: any) => {
            if (obj.isMesh) obj.castShadow = true;
        });
        remoteModel.position.copy(tempModel.position);
        remoteModel.rotation.copy(tempModel.rotation);
        remoteModel.name = `remote_${id}`;

        const mixer = new THREE.AnimationMixer(remoteModel);
        const actions = {} as Record<AnimationType, THREE.AnimationAction>;

        gltf.animations.forEach(clip => {
            const clipName = clip.name as AnimationType;
            const action = mixer.clipAction(clip);
            actions[clipName] = action;
            action.enabled = true;
            action.setEffectiveWeight(0);
            // 添加循环模式设置
            action.setLoop(THREE.LoopRepeat, Infinity);
            action.play();
        });

        actions[ANIMATION.IDLE].setEffectiveWeight(1);

        that.scene.remove(tempModel);
        that.scene.add(remoteModel);

        remotePlayers[id] = {
            ...remotePlayers[id],
            model: remoteModel,
            mixer,        // 保存动画混合器
            actions,      // 保存动画动作
            currentAction: ANIMATION.IDLE, // 初始化动作状态
            collider,
            velocity: remotePlayers[id].velocity,
            targetPosition: remotePlayers[id].targetPosition
        };

        // 创建ID显示画布
        const createIdSprite = () => {
            const canvas = document.createElement('canvas');
            canvas.width = 512;
            canvas.height = 128;
            const ctx = canvas.getContext('2d')!;

            // 绘制背景
            ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
            ctx.beginPath();
            ctx.roundRect(0, 0, canvas.width, canvas.height, 8);
            ctx.fill();

            // 绘制文本
            ctx.fillStyle = 'white';
            ctx.font = '36px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(`${id}`, canvas.width / 2, canvas.height / 2);

            // 创建精灵材质
            const texture = new THREE.CanvasTexture(canvas);
            const material = new THREE.SpriteMaterial({
                map: texture,
                transparent: true,
                depthTest: false
            });

            // 创建精灵对象
            const sprite = new THREE.Sprite(material);
            sprite.scale.set(1, 0.5, 1);  // 根据画布比例调整
            sprite.position.set(0, 2, 0); // 头顶位置
            sprite.renderOrder = 999;      // 确保始终显示在最前面

            return sprite;
        };

        // 将ID精灵添加到模型
        const idSprite = createIdSprite();
        remoteModel.add(idSprite);

        socket.on('playerDisconnected', (disconnectedId: string) => {
            if (disconnectedId === id) {
                // 移除场景中的模型
                that.scene.remove(remotePlayers[id].model);
                // 停止动画混合器
                remotePlayers[id].mixer?.stopAllAction();
                // 材质清理
                idSprite.material.map?.dispose();
                idSprite.material.dispose();
                remoteModel.remove(idSprite);
                // 删除玩家数据
                delete remotePlayers[id];
                ElMessage.warning(`玩家 ${id} 已断开连接`);

                // 清理场景中的宝箱提示资源
                if (chestHintSprite) {
                    chestHintSprite.material.map?.dispose();
                    chestHintSprite.material.dispose();
                    chest?.remove(chestHintSprite);
                }
            }
        });
    });
}
//#endregion

/**
 * 更新游戏逻辑：
 *  - 处理输入与控制
 *  - 更新本地玩家状态
 *  - 更新远程玩家数据和动画
 */
export function gameUpdate(deltaTime: number) {
    controls(deltaTime);
    updatePlayer(deltaTime);
    teleportPlayerIfOob();
    updateRainEffect(deltaTime)

    // 宝箱提示检测
    if (chest && that.player && chestHintSprite) {
        const distance = that.player.position.distanceTo(chest.position);
        chestHintSprite.visible = !isChestOpen && distance < 3; // 3米内显示提示

        // 使提示始终面向相机
        chestHintSprite.lookAt(that.camera.position);
    }

    // 宝箱互动检测
    if (chest && that.player && !isChestOpen) {
        // 计算玩家与宝箱的距离
        const distance = that.player.position.distanceTo(chest.position);

        // 当距离小于2单位且按下F键时
        if (distance < 2 && keyStates.KeyF) {
            chestAction?.play();
            isChestOpen = true;
            ElMessage.success("宝箱已开启！");
        }
    }

    // 更新宝箱动画
    if (chestMixer) {
        chestMixer.update(deltaTime);
    }

    if (localPlayerId && that.player) {
        socket.emit('playerMove', {
            position: {
                x: that.player.position.x,
                y: that.player.position.y,
                z: that.player.position.z
            },
            rotation: {
                x: that.player.rotation.x,
                y: that.player.rotation.y,
                z: that.player.rotation.z
            },
            action: that.currentAction.name
        });
    }

    Object.values(remotePlayers).forEach(player => {
        player.velocity.y -= GRAVITY * deltaTime;
        player.collider.translate(player.velocity.clone().multiplyScalar(deltaTime));
        player.model.position.lerp(player.targetPosition, 0.3);
        player.model.rotation.copy(player.targetRotation);

        const result = worldOctree.capsuleIntersect(player.collider);
        player.onFloor = false;
        if (result) {
            player.onFloor = result.normal.y > 0;
            if (!player.onFloor) {
                player.velocity.addScaledVector(result.normal, -result.normal.dot(player.velocity));
            }
            player.collider.translate(result.normal.multiplyScalar(result.depth));
        }
        player.model.position.lerp(player.targetPosition, 0.3);
        player.model.rotation.copy(player.targetRotation);
        player.mixer?.update(deltaTime);
    });
}

/**
 * 游戏初始化入口：
 *  - 设置网络通信、注册事件监听
 *  - 构建场景、加载模型和动画资源
 *  - 初始化调试信息及控制面板
 */
export function gameInit(th: any) {
    that = th;
    socket = io('http://localhost:3000');

    // 添加下雨效果
    createRainEffect();

    // Socket 事件注册
    socket.on('connect', () => {
        localPlayerId = socket.id;
    });

    socket.on('init', (data: { players: Record<string, PlayerState> }) => {
        Object.entries(data.players).forEach(([id, state]) => {
            if (id !== socket.id) {
                const position = new THREE.Vector3(state.position.x, state.position.y, state.position.z);
                const rotation = new THREE.Euler(state.rotation.x, state.rotation.y, state.rotation.z, 'XYZ');
                createRemotePlayer(id, position, rotation);
            }
        });
    });

    socket.on('playerConnected', (data: { id: string; state: PlayerState }) => {
        if (data.id !== socket.id) {
            const position = new THREE.Vector3(data.state.position.x, data.state.position.y, data.state.position.z);
            const rotation = new THREE.Euler(data.state.rotation.x, data.state.rotation.y, data.state.rotation.z, 'XYZ');
            createRemotePlayer(data.id, position, rotation);
        }
    });

    socket.on('playerMoved', (data: any) => {
        const remotePlayer = remotePlayers[data.id];
        if (!remotePlayer) return;
        remotePlayer.targetPosition.set(data.position.x, data.position.y, data.position.z);
        remotePlayer.targetRotation.set(data.rotation.x, data.rotation.y, data.rotation.z, 'XYZ');

        if (data.action && remotePlayer.actions[data.action]) {
            if (remotePlayer.currentAction !== data.action) {
                // 获取新旧动作引用
                const prevAction = remotePlayer.actions[remotePlayer.currentAction];
                const newAction = remotePlayer.actions[data.action];

                // 设置新旧动作的交叉淡入淡出
                prevAction?.fadeOut(0.2);    // 淡出旧动作
                newAction
                    .reset()               // 重置动画时间线
                    .setEffectiveWeight(1) // 设置目标权重为1
                    .fadeIn(0.2)           // 淡入新动作
                    .play();               // 必须调用play()

                remotePlayer.currentAction = data.action;
            }
        }
    });

    // 注册键盘与鼠标事件
    let keyW = false;
    document.addEventListener('keydown', (event: KeyboardEvent) => {
        switch (event.code) {
            case 'KeyW':
                keyStates.W = true;
                playerActionState.forward = 1;
                if (!keyW) {
                    ForwardHoldTimeClock.start();
                    keyW = true;
                    keyStates.ShiftLeft = false;
                }
                break;
            case 'ShiftLeft':
                keyStates.ShiftLeft = true;
                break;
            case 'KeyA':
                keyStates.A = true;
                playerActionState.turn = -1;
                break;
            case 'KeyS':
                keyStates.S = true;
                playerActionState.forward = -1;
                break;
            case 'KeyD':
                keyStates.D = true;
                playerActionState.turn = 1;
                break;
            case 'Space':
                keyStates.Space = true;
                break;
            case 'KeyF':
                keyStates.KeyF = true;
                break;
        }
    });

    document.addEventListener('keyup', (event: KeyboardEvent) => {
        switch (event.code) {
            case 'KeyW':
                keyW = false;
                keyStates.W = false;
                playerActionState.forward = 0;
                ForwardHoldTimeClock.stop();
                ForwardHoldTimeClock.elapsedTime = 0;
                break;
            case 'KeyA':
                keyStates.A = false;
                playerActionState.turn = 0;
                break;
            case 'KeyS':
                keyStates.S = false;
                playerActionState.forward = 0;
                break;
            case 'KeyD':
                keyStates.D = false;
                playerActionState.turn = 0;
                break;
            case 'Space':
                keyStates.Space = false;
                break;
            case 'KeyF':
                keyStates.KeyF = false;
                break;
        }
        // 恢复按键状态
        playerActionState.forward = keyStates.W ? 1 : playerActionState.forward;
        playerActionState.turn = keyStates.A ? -1 : playerActionState.turn;
        playerActionState.forward = keyStates.S ? -1 : playerActionState.forward;
        playerActionState.turn = keyStates.D ? 1 : playerActionState.turn;
    });

    that.container.addEventListener('mousedown', (e: MouseEvent) => {
        obj.look ? document.body.requestPointerLock() : document.exitPointerLock();
        if (e.button === 0) keyStates.leftMouseBtn = true;
    });

    document.addEventListener('mouseup', (e: MouseEvent) => {
        if (e.button === 0) keyStates.leftMouseBtn = false;
    });

    document.body.addEventListener('mousemove', (event: MouseEvent) => {
        if (document.pointerLockElement === document.body) {
            that.player.rotation.y -= event.movementX / (cameraMoveSensitivity * 1000);
            that.camera.rotation.x = THREE.MathUtils.clamp(
                that.camera.rotation.x - event.movementY / (cameraMoveSensitivity * 1000),
                -Math.PI / 8,
                Math.PI / 8
            );
        } else if (keyStates.leftMouseBtn) {
            if (cameraMoveSensitivity <= 0) cameraMoveSensitivity = 0.001;
            if (cameraMoveSensitivity > 1) cameraMoveSensitivity = 1;
            that.player.rotation.y -= event.movementX / (cameraMoveSensitivity * 1000);
            that.camera.rotation.x = THREE.MathUtils.clamp(
                that.camera.rotation.x - event.movementY / (cameraMoveSensitivity * 1000),
                -Math.PI / 8,
                Math.PI / 8
            );
        }
    });

    gui.add(obj, "look").name("是否锁定鼠标").onChange((value) => { obj.look = value; });

    // 资源加载：模型、场景与动画
    const loader = new GLTFLoader().setPath('/models/');
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('/draco/');
    loader.setDRACOLoader(dracoLoader);

    // 加载比奇堡
    loader.load("bfbb_glb/source/bikinibottom.glb", (gltf) => {
        gltf.scene.position.set(-10, -10, 0);
        gltf.scene.rotation.y = -Math.PI / 2;
        that.scene.add(gltf.scene);
        worldOctree.fromGraphNode(gltf.scene);
        gltf.scene.traverse((child) => {
            if (child instanceof THREE.Mesh) {
                child.castShadow = true;
                child.receiveShadow = true;
                if (child.material.map) child.material.map.anisotropy = 4;
            }
        });
        const helper = new OctreeHelper(worldOctree);
        helper.visible = false;
        that.scene.add(helper);
        gui.add({ OctreeDebug: false }, 'OctreeDebug')
            .onChange((value: boolean) => { helper.visible = value; });
    });

    // 加载宝箱
    loader.load('bx.glb', (gltf) => {
        gltf.scene.scale.set(0.5, 0.5, 0.5);
        gltf.scene.rotation.y = 28.6;
        gltf.scene.position.set(1.03, -5, 2.87);
        worldOctree.fromGraphNode(gltf.scene);
        that.scene.add(gltf.scene);

        // 保存宝箱引用
        chest = gltf.scene;

        // 初始化动画混合器
        chestMixer = new THREE.AnimationMixer(chest);
        if (gltf.animations.length > 0) {
            chestAction = chestMixer.clipAction(gltf.animations[0]);
            chestAction.setLoop(THREE.LoopOnce, 1);  // 只播放一次
            chestAction.clampWhenFinished = true;    // 停留在最后一帧
        }

        // 创建提示精灵
        const createHintSprite = () => {
            const canvas = document.createElement('canvas');
            canvas.width = 512;
            canvas.height = 128;
            const ctx = canvas.getContext('2d')!;

            // 绘制背景和文字
            ctx.fillStyle = 'rgba(0, 150, 255, 0.8)';
            ctx.beginPath();
            ctx.roundRect(0, 0, canvas.width, canvas.height, 20);
            ctx.fill();

            ctx.fillStyle = 'white';
            ctx.font = '48px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText('按下 F 开启宝箱', canvas.width / 2, canvas.height / 2);

            // 创建材质
            const texture = new THREE.CanvasTexture(canvas);
            const material = new THREE.SpriteMaterial({
                map: texture,
                transparent: true,
                depthTest: false
            });

            // 创建精灵并定位
            const sprite = new THREE.Sprite(material);
            sprite.scale.set(1.5, 0.5, 1); // 根据画布比例调整
            sprite.position.set(0, 2.5, 0); // 宝箱上方2.5个单位
            sprite.visible = false; // 初始隐藏

            return sprite;
        };

        chestHintSprite = createHintSprite();
        gltf.scene.add(chestHintSprite);
    });

    // 加载本地玩家 shandy/scene.gltf
    loader.load("fish.glb", (gltf) => {
        that.player = gltf.scene;

        // 生成安全出生点
        const getRandomSpawnPosition = () => {
            const maxAttempts = 100;
            for (let i = 0; i < maxAttempts; i++) {
                // 生成随机坐标（根据场景大小调整范围）
                const pos = new THREE.Vector3(
                    THREE.MathUtils.randFloatSpread(100),  // X轴范围
                    DEFAULT_COLLIDER_TOP_Y,               // 初始Y坐标
                    THREE.MathUtils.randFloatSpread(100)   // Z轴范围
                );

                // 创建临时碰撞体检测
                const tempCollider = new Capsule(
                    new THREE.Vector3(pos.x, pos.y - DEFAULT_COLLIDER_BOTTOM_Y, pos.z),
                    new THREE.Vector3(pos.x, pos.y + DEFAULT_COLLIDER_TOP_Y, pos.z),
                    DEFAULT_COLLIDER_RADIUS
                );

                // 检测碰撞
                if (!worldOctree.capsuleIntersect(tempCollider)) {
                    return pos;
                }
            }
            return new THREE.Vector3(0, DEFAULT_COLLIDER_TOP_Y, 0);
        };

        // 设置玩家初始位置
        that.player.position.copy(getRandomSpawnPosition());

        // 更新碰撞体位置
        playerCollider.start.set(
            that.player.position.x,
            that.player.position.y - DEFAULT_COLLIDER_BOTTOM_Y,
            that.player.position.z
        );
        playerCollider.end.set(
            that.player.position.x,
            that.player.position.y + DEFAULT_COLLIDER_TOP_Y,
            that.player.position.z
        );

        that.scene.add(that.player);
        that.player.add(that.camera);
        that.player.add(playerColliderHelper);
        playerColliderHelper.visible = false;
        that.player.traverse((object: THREE.Mesh) => { if (object.isMesh) object.castShadow = true; });
        that.mixer = new THREE.AnimationMixer(that.player);
        that.allActions = {};
        gltf.animations.forEach((clip) => {
            const action = that.mixer.clipAction(clip);
            action.name = clip.name;
            action.setEffectiveWeight(0);
            // 添加循环模式设置
            action.setLoop(THREE.LoopRepeat, Infinity);
            action.play();
            that.allActions[action.name] = action;
        });
        that.allActions[ANIMATION.IDLE].setEffectiveWeight(1);
        that.currentAction = that.allActions[ANIMATION.IDLE];
    });

    // 加载Boss
    loader.load('bot_boss/scene.gltf', (gltf) => {
        gltf.scene.scale.set(0.08, 0.08, 0.08);
        gltf.scene.rotation.y = Math.PI;
        worldOctree.fromGraphNode(gltf.scene);
        that.scene.add(gltf.scene);
        model = gltf.scene;
        const texture = new THREE.TextureLoader().load("/textures/BOSS.png");
        const sprite = new THREE.Sprite(new THREE.SpriteMaterial({
            map: texture,
            transparent: true,
            color: 0xffffff,
            opacity: 0.9,
        }));
        sprite.scale.set(20, 10, 10);
        sprite.position.set(0.5, 35, -1);
        sprite.renderOrder = 999;
        model.add(sprite);

        const mixer = new THREE.AnimationMixer(gltf.scene);
        const clipAction = mixer.clipAction(gltf.animations[6]);
        clipAction.play();
        const clock = new THREE.Clock();
        function loop() {
            requestAnimationFrame(loop);
            mixer.update(clock.getDelta());
        }
        loop();
    });

    // 初始化曲线与动画
    makeCurve();
    animateCurve();
    gui.add({ colliderHelper: false }, 'colliderHelper')
        .name("胶囊护体")
        .onChange((value: boolean) => { playerColliderHelper.visible = value; });

    createDebugOverlay();
}
